﻿using System;
using System.DirectoryServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Twittscrobbler
{
    public class AESuru
    {
        static string password;

        //暗号複合用ユーザ固有ID取得
        public AESuru(){
            DirectoryEntry root = new DirectoryEntry("WinNT://" + Environment.MachineName
            + "/" + Environment.UserName, null, null, AuthenticationTypes.Secure);
            System.Array ob = (System.Array)root.Properties["objectsid"][0];
            for (int i = 0; i < ob.Length; i++)
            {
                password += ((byte)ob.GetValue(i)).ToString("X2");
            }
        }

        //暗号化
        public void Encrypt(string filename, string str)
        {

            //AesCryptoServiceProviderオブジェクトの作成
            System.Security.Cryptography.AesCryptoServiceProvider
              aes = new System.Security.Cryptography.AesCryptoServiceProvider();

            //※AESはブロックサイズ、キー長ともに128bit
            aes.BlockSize = 128;                                          //ブロックサイズ
            aes.KeySize = 128;                                            //キー最大長
            aes.Mode = System.Security.Cryptography.CipherMode.CBC;       //CBCモード
            aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7; //パディングモード

            //初期化ベクトルの設定と取得（ブロックサイズと同サイズ=128bit）
            aes.GenerateIV();
            byte[] bytesIV = aes.IV;

            //パスワードを適切な書式に処理する
            byte[] bytesPassword = System.Text.Encoding.UTF8.GetBytes(password);
            byte[] bytesKey = new byte[16];    //キー長128bit

            //有効なキーサイズになっていない場合は調整する
            for (int i = 0; i < 16; i++)
            {
                if (i < bytesPassword.Length)
                {
                    bytesKey[i] = bytesPassword[i];
                }
                else
                {
                    bytesKey[i] = 0;  //余白はゼロで埋める
                }
            }

            aes.Key = bytesKey; //処理済みパスワードをセット

            //AES暗号化オブジェクトの作成
            System.Security.Cryptography.ICryptoTransform encrypt = aes.CreateEncryptor();

            //FileStreamの生成
            System.IO.FileStream outfs = new System.IO.FileStream(
                filename, System.IO.FileMode.Create, System.IO.FileAccess.Write);

            //IVを先頭に書き込む(128bit=16bytes)
            outfs.Write(bytesIV, 0, 16);

            //CryptoStreamの作成
            System.Security.Cryptography.CryptoStream
              cs = new System.Security.Cryptography.CryptoStream(
                outfs, encrypt, System.Security.Cryptography.CryptoStreamMode.Write);

            //暗号化データを書き出していく
            System.IO.MemoryStream fs = new System.IO.MemoryStream
               (System.Text.Encoding.UTF8.GetBytes(str));


            byte[] buffer = new byte[1024];

            int len;

            while ((len = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                cs.Write(buffer, 0, len);
            }

            //閉じる
            fs.Close();
            cs.Close();
            encrypt.Dispose();
            outfs.Close();

        }
        //復号化
        public string Decrypt(string filename)
        {

            //AesCryptoServiceProviderオブジェクトの作成
            System.Security.Cryptography.AesCryptoServiceProvider
              aes = new System.Security.Cryptography.AesCryptoServiceProvider();

            //※AESはブロックサイズ、キー長ともに128bit
            aes.BlockSize = 128;                                          //ブロックサイズ
            aes.KeySize = 128;                                            //キー最大長
            aes.Mode = System.Security.Cryptography.CipherMode.CBC;       //CBCモード
            aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7; //パディングモード

            //パスワードを適切な書式に処理する
            byte[] bytesPassword = System.Text.Encoding.UTF8.GetBytes(password);
            byte[] bytesKey = new byte[16];    //キー長128bit
            byte[] bytesIV = new byte[16];
            string decrypt_;

            //有効なキーサイズになっていない場合は調整する
            for (int i = 0; i < 16; i++)
            {
                if (i < bytesPassword.Length)
                {
                    bytesKey[i] = bytesPassword[i];
                }
                else
                {
                    bytesKey[i] = 0;
                }
            }

            aes.Key = bytesKey; //パスワード

            //暗号化データを読み込んでいく
            System.IO.FileStream fs = new System.IO.FileStream(
                filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            //IVを先頭から取り出してAesCryptoServiceProviderオブジェクトにセット
            fs.Read(bytesIV, 0, 16);
            aes.IV = bytesIV;

            //AES 復号オブジェクトの作成
            System.Security.Cryptography.ICryptoTransform encrypt = aes.CreateDecryptor();

            //FileStreamの生成
            System.IO.MemoryStream outfs = new System.IO.MemoryStream();

            //CryptoStreamの作成
            System.Security.Cryptography.CryptoStream
              cs = new System.Security.Cryptography.CryptoStream(
                outfs, encrypt, System.Security.Cryptography.CryptoStreamMode.Write);

            byte[] buffer = new byte[1024];

            int len;

            while ((len = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                cs.Write(buffer, 0, len);
            }
            len = 0;
            cs.FlushFinalBlock();
            cs.Flush();


            byte[] bss = new byte[outfs.Length];
            outfs.Position = 0;

            outfs.Read(bss, 0, bss.Length);
            decrypt_ = System.Text.Encoding.UTF8.GetString(bss);

            //閉じる
            fs.Close();
            cs.Close();
            encrypt.Dispose();
            outfs.Close();

            return decrypt_;
        }
    }
}
